#ifndef _MESSAGE_H__
#define _MESSAGE_H__

#include "os/types.h"
#include "bsp/bsp.h"
#include "config.h"

typedef struct {
	u16 key;
	u8 dest;
	u8 src;
	u8 *data;
	u16 len;
	u8 idx;
	u8 total_frame;	
	u8 type;	
}message_t;

typedef union {
	uint32_t id;
	struct {
		uint32_t	dest		:7; /*bit 0-6  */
		uint32_t	src 		:7; /*bit 7-13 */
		uint32_t	idx 		:5; /*bit 14-18 */
		uint32_t	total		:5; /*bit 19-23 */
		uint32_t	type		:2; /*bit 24-25 */ /*1:PT_REQ_NEED_RES ; 2:PT_RES 3:PT_REQ_NO_IND*/
		uint32_t	retry		:3; /*bit 26-28 */
		uint32_t	length 		:3; /*bit 29-13 */ //0-7:1-8
	};
}head_t;

//total 29bits efid
typedef union {
	uint32_t id;
	struct {
		uint32_t	dest		:6; /*bit 0-5  */
		uint32_t	src 		:6; /*bit 6-11 */
		uint32_t	idx 		:4; /*bit 12-15 */
		uint32_t	total		:4; /*bit 16-19 */
		uint32_t	cmd			:7; /*bit 20-26 */		
		uint32_t    type        :2; /*bit 27-28, 0x1:request, 0x2:indicat/ack, 0x3:Invald */  
	}ext;
	struct {
		uint32_t	dest		:6; /*bit 0-5  */
		uint32_t	src 		:6; /*bit 6-11 */
		uint32_t	cmd 		:15; /*bit 12-26 */
		uint32_t    type        :2; /*bit 27-28, 0x0 */  
	}basic;
}head_new_t;

static __INLINE uint32 get_can_id(u8 dest, u8 src, u8 type, u8 retry){
	head_t id;
	id.id = 0;
	id.dest = dest;
	id.src = src;
	id.type = type;
	id.retry = retry;
	return id.id;
}

#define ptype_beat_heart		0 // can heat heart
#define ptype_request  	1 // can request with need response
#define ptype_response			2 // can response of the request
#define ptype_indicater	3 // can request with no need response

#define MY_MESSAGE_ADDR CONFIG_CAN_ADDRESS

#define MESSAGE_MAX_FRAMES		32

#define BUILD_CMD_KEY(key)		(MY_MESSAGE_ADDR << 8 | (key))

static __INLINE uint16_t decoder_key(const void *buf){
	uint8_t *key_buf = (uint8_t *)buf;
	return key_buf[1]<<8 | key_buf[0];
} 

//used when can send
static __INLINE void encoder_key(uint8_t *buff, uint16_t key) {
	buff[0] = key & 0xFF;
	buff[1] = (key >> 8) & 0xFF;
}

static __INLINE uint32 request_head(u8 dest, u8 retry){
	return get_can_id(dest,MY_MESSAGE_ADDR, ptype_request, retry);
}

static __INLINE uint32 indicator_head(u8 dest){
	return get_can_id(dest,MY_MESSAGE_ADDR, ptype_indicater, 1);
}

static __INLINE uint32 response_head(u8 dest){
	return get_can_id(dest,MY_MESSAGE_ADDR, ptype_response, 1);
}

void message_init(void);
s32 message_send(uint32_t head, u8 *data, int len, s32 timeout);
void message_send_ack(message_t *msg, uint8_t success);
void message_send_ack2(uint8_t addr, uint16_t key, uint8_t data);
void message_send_response(uint8_t addr, uint8_t *data, int len);
void message_send_indicator(uint8_t addr, uint8_t *data, int len);
void message_send_request(uint8_t addr, uint8_t *data, int len);
#endif /* _MESSAGE_H__ */
